#include "../../include/pagelib/DataStore.h"
#include "../../include/pagelib/Configuration.h"
#include "../../include/pagelib/MyLogger.h"

#include <fstream>
#include <sstream>
#include <vector>

using namespace std;

DataStore::DataStore()
: _dataSql()
, _configMap(Configuration::getInstance()->getConfigMap()) 
{

}

DataStore::~DataStore()
{

}

// 将数据存储到mysql数据库
void DataStore::storeToDataBase()
{
    // 保存网页库
    storeWebPageLib();
    // 保存网页偏移库
    storeOffsetLib();
    // 保存倒排索引库
    storeInvertIndexLib();

    // 保存英文词频库
    storeEnDict();
    // 保存英文索引
    storeEnDictIndex();
    // 保存中文词频库
    storeCnDict();
    // 保存中文索引
    storeCnDictIndex();
}

// 处理 SQL 字符串转义，防止 SQL 注入
string DataStore::escapeString(const string &input)
{
    string output;
    for (char c : input)
    {
        if (c == '\'' || c == '"' || c == '\\')
            output += '\\';
        output += c;
    }
    return output;
}

// 辅助函数: 连接字符串
// 作用: 将字符串向量 vec 中的所有元素按照指定的分隔符 delimiter 进行拼接，形成一个完整的字符串。
// 例如：输入 vec = {"a", "b", "c"}, delimiter = ", "，返回结果 "a, b, c"
string DataStore::join(const vector<string> &vec, const string &delimiter) 
{
    ostringstream oss; // 使用 ostringstream 来高效拼接字符串

    for (size_t i = 0; i < vec.size(); ++i) // 遍历vector中的所有字符串
    {
        if (i > 0) // 在第一个元素之后，每个元素前面添加分隔符
            oss << delimiter;
        oss << vec[i]; // 添加字符串元素到 oss
    }

    return oss.str(); // 返回拼接后的字符串
}

// 辅助函数: 去除首尾空格
// 作用: 去掉字符串 s 两端的空白字符（空格、制表符、换行符等），返回处理后的字符串。
// 例如：输入 "  hello world  "，返回 "hello world"
string DataStore::trim(const string &s) 
{
    // 找到第一个非空白字符的位置
    size_t start = s.find_first_not_of(" \t\r\n"); 

    // 找到最后一个非空白字符的位置
    size_t end = s.find_last_not_of(" \t\r\n");    

    // 如果字符串全是空白字符，start 会是 npos，直接返回空字符串
    return (start == string::npos) ? "" : s.substr(start, end - start + 1);
}

// 通用 SQL 执行方法
// 作用: 执行 SQL 语句，并记录日志。如果执行失败，则捕获异常并打印错误信息。
// 该方法用于减少重复代码，使所有的 SQL 执行逻辑都集中在这里处理，提高代码可维护性和可读性。
void DataStore::executeSQL(const string &sql, const string &logMessage) 
{
    try 
    {
        _dataSql.update(sql); // 执行 SQL 语句
        LogInfo(logMessage);  // 记录 SQL 执行成功的日志
    } 
    catch (exception &e) // 捕获可能出现的异常
    {
        LogError("SQL 执行失败: " + string(e.what()));
    }
}


// 保存网页库
void DataStore::storeWebPageLib()
{
    ifstream ifs(_configMap["formatWebpage.dat"]);
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["formatWebpage.dat"]);
        return;
    }

    vector<string> values;
    string line;
    while (getline(ifs, line))
    {
        values.push_back("('" + escapeString(line) + "')");
    }
    ifs.close();

    if (!values.empty())
    {
        string sql = "INSERT INTO formatWebpage(content) VALUES " + join(values, ",") + ";";
        executeSQL(sql, "storeWebPageLib");
    }
}

// 保存网页偏移库
void DataStore::storeOffsetLib()
{
    ifstream ifs(_configMap["offsetLib.dat"]);
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["offsetLib.dat"]);
        return;
    }

    vector<string> values;
    int docid, startPos, length;
    while (ifs >> docid >> startPos >> length)
    {
        values.push_back("(" + to_string(docid) + "," + to_string(startPos) + "," + to_string(length) + ")");
    }
    ifs.close();

    if (!values.empty())
    {
        string sql = "INSERT INTO offset(docid, startPos, length) VALUES " + join(values, ",") + ";";
        executeSQL(sql, "storeOffsetLib");
    }
}

// 保存倒排索引库
void DataStore::storeInvertIndexLib()
{
    ifstream ifs(_configMap["invertIndex.dat"]); // 打开倒排索引数据文件
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["invertIndex.dat"]);
        return;
    }

    vector<string> values; // 用于存储 SQL 插入语句的值
    string word, content;
    while (ifs >> word && getline(ifs, content)) 
    {
        if(word.length() > 64)
        {
            LogError("词过长，跳过："+word);
            continue;     // 跳过这个超长词
        }
        values.push_back("('" + escapeString(word) + "','" + escapeString(trim(content)) + "')");
    }
    ifs.close();

    if (!values.empty()) 
    {
        // 使用 ON DUPLICATE KEY UPDATE 避免重复主键错误
        string sql = "INSERT INTO invert_index(word, content) VALUES " + join(values, ",") +
                     " ON DUPLICATE KEY UPDATE content=VALUES(content);";
        executeSQL(sql, "storeInvertIndexLib");
    }
}


// 保存英文词频库
void DataStore::storeEnDict()
{
    ifstream ifs(_configMap["eg_dict.dat"]);
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["eg_dict.dat"]);
        return;
    }

    vector<string> values;
    string word, frequency;
    int lineNumber = 1;
    while (ifs >> word >> frequency)
    {
        values.push_back("(" + to_string(lineNumber++) + ",'" + escapeString(word) + "'," + frequency + ")");
    }
    ifs.close();

    if (!values.empty())
    {
        string sql = "INSERT INTO en_dict(linenum, word, frequency) VALUES " + join(values, ",") + ";";
        executeSQL(sql, "storeEnDict");
    }
}

// 保存英文索引
void DataStore::storeEnDictIndex()
{
    ifstream ifs(_configMap["eg_dictIndex.dat"]);
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["eg_dictIndex.dat"]);
        return;
    }

    vector<string> values;
    string word, content;
    while (ifs >> word && getline(ifs, content))
    {
        values.push_back("('" + escapeString(word) + "','" + escapeString(trim(content)) + "')");
    }
    ifs.close();

    if (!values.empty())
    {
        string sql = "INSERT INTO en_dict_index(word, content) VALUES " + join(values, ",") + ";";
        executeSQL(sql, "storeEnDictIndex");
    }
}

// 保存中文词频库
void DataStore::storeCnDict()
{
    ifstream ifs(_configMap["cn_dict.dat"]);
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["cn_dict.dat"]);
        return;
    }

    vector<string> values;
    string word, frequency;
    int lineNumber = 1;
    while (ifs >> word >> frequency)
    {
        values.push_back("(" + to_string(lineNumber++) + ",'" + escapeString(word) + "'," + frequency + ")");
    }
    ifs.close();

    if (!values.empty())
    {
        string sql = "INSERT INTO cn_dict(linenum, word, frequency) VALUES " + join(values, ",") + ";";
        executeSQL(sql, "storeCnDict");
    }
}

// 保存中文索引
void DataStore::storeCnDictIndex()
{
    ifstream ifs(_configMap["cn_dictIndex.dat"]);
    if (!ifs)
    {
        LogError("无法打开文件: " + _configMap["cn_dictIndex.dat"]);
        return;
    }

    vector<string> values;
    string word, content;
    while (ifs >> word && getline(ifs, content))
    {
        values.push_back("('" + escapeString(word) + "','" + escapeString(trim(content)) + "')");
    }
    ifs.close();

    if (!values.empty())
    {
        string sql = "INSERT INTO cn_dict_index(word, content) VALUES " + join(values, ",") + ";";
        executeSQL(sql, "storeCnDictIndex");
    }
}
